<template>
  <div v-if="hasPermission" class="bs-page-design-wrap">
    <PageTopSetting v-show="headerShow" ref="PageTopSetting" :right-fold="rightVisiable"
      @updateRightVisiable="updateRightVisiable" @showPageInfo="showPageInfo" @changeZoom="changeScreenZoom"
      @empty="empty" />
    <div class="drag-wrap">
      <!-- 左侧面板 -->
      <LeftPanel :header-show="headerShow" :height="height" @openRightPanel="openRightPanel" @openResource="initDialog"
        @openComponent="openComponent" @toggleLeftSidebar="toggleLeftSidebar" />
      <!-- 中间组件展示面板 -->
      <div v-loading="pageLoading" class="grid-wrap-box" :style="{
        height: 'calc(100vh - 48px)'
      }" tabindex="1000" @keydown="designKeydown">
        <div id="minimap" class="minimap">
          <div class="mapHeader" id="mapHeader">
            <div>
              <span>小地图</span>
            </div>
            <div class="showMap" @click="showMinimap">
              <i class="el-icon-arrow-down" style="width:20px;height:20px;color:#fff;" v-if="!mapShow" />
              <i class="el-icon-arrow-up" style="width:20px;height:20px;color:#fff;" v-if="mapShow" />
            </div>
          </div>
          <div id="selectWin" class="selectWin" v-show="mapShow">
            <div id="selectionWin" class="selectionWin" />
          </div>
        </div>
        <SketchDesignRuler ref="Rules" :width="3000" :height="3000" :page-width="pageConfig.w"
          :page-height="pageConfig.h" @changeStart="changeStart">
          <MouseSelect :offset-x="offset.x" :offset-y="offset.y" @selectArea="onSelectArea">
            <Render ref="Render" :class="{
              'grid-bg': hasGrid
            }" @openRightPanel="openRightPanel" @openDataViewDialog="openDataViewDialog" />
          </MouseSelect>
        </SketchDesignRuler>
        <!-- <div class="footer-tools-bar">
          <el-slider
            class="bs-slider-wrap"
            :value="zoom"
            :min="10"
            style="width: 200px; margin-right: 20px"
            @input="changeScreenZoom"
          />
          <span class="select-zoom-text">缩放比例</span>
          <el-select
            class="bs-el-select"
            popper-class="bs-el-select"
            :value="zoom"
            @change="changeScreenZoom"
          >
            <el-option
              v-for="(zoom,index) in zoomList"
              :key="index"
              :label="zoom.label"
              :value="zoom.value"
            />
          </el-select>
        </div> -->
      </div>
      <!-- 右侧折叠设置面板   -->
      <SettingPanel :header-show="headerShow" :height="height" :right-visiable.sync="rightVisiable"
        :page-info-visiable="pageInfoVisiable" @updateSetting="updateSetting" @updateDataSetting="updateDataSetting"
        @updatePage="updatePage" @styleHandler="styleHandler">
        <template #dataSetSelect="{ value }">
          <slot name="dataSetSelect" :value="value" />
        </template>
      </SettingPanel>
      <!-- 添加资源面板 -->
      <SourceDialog ref="SourceDialog" @getImg="setImg" />
      <ComponentDialog ref="componentDialog" @setComponent="setComponent" @setRemoteComponent="setRemoteComponent" />
      <iframe-dialog v-if="iframeDialog" ref="iframeDialog" />
    </div>
    <data-view-dialog ref="dataViewDialog" />
  </div>
  <NotPermission v-else-if="!hasPermission" />
</template>
<script>
import SourceDialog from './SourceDialog/index.vue'
import ComponentDialog from './ComponentDialog/index.vue'
import iframeDialog from 'data-room-ui/BasicComponents/LinkChart/iframeDialog'
import {
  dataConfig,
  settingConfig
} from 'data-room-ui/BasicComponents/Picture/settingConfig'
import LeftPanel from './LeftPanel.vue'
import SettingPanel from './SettingPanel.vue'
import PageTopSetting from './PageDesignTop.vue'
import Render from '../Render'
import { mapActions, mapMutations, mapState } from 'vuex'
import SketchDesignRuler from 'data-room-ui/BigScreenDesign/RulerTool/SketchRuler.vue'
import multipleSelectMixin from 'data-room-ui/js/mixins/multipleSelectMixin'
import { getScreenInfo } from 'data-room-ui/js/api/bigScreenApi'
import plotSettings from 'data-room-ui/G2Plots/settings'
import MouseSelect from './MouseSelect/index.vue'
import cloneDeep from 'lodash/cloneDeep'
import { randomString } from '../js/utils'
import { isFirefox } from 'data-room-ui/js/utils/userAgent'
import { handleResData } from 'data-room-ui/js/store/actions.js'
import { EventBus } from 'data-room-ui/js/utils/eventBus'
import NotPermission from 'data-room-ui/NotPermission'
import DataViewDialog from 'data-room-ui/BigScreenDesign/DataViewDialog'
export default {
  name: 'BigScreenDesign',
  components: {
    PageTopSetting,
    LeftPanel,
    Render,
    SketchDesignRuler,
    MouseSelect,
    SettingPanel,
    SourceDialog,
    ComponentDialog,
    iframeDialog,
    NotPermission,
    DataViewDialog
  },
  mixins: [multipleSelectMixin],
  props: {
    code: {
      type: String,
      default: ''
    },
    headerShow: {
      type: Boolean,
      default: true
    },
    height: {
      type: String,
      default: 'calc(100vh - 40px)'
    }
  },
  data() {
    return {
      mapShow: true, // 小地图显示与否
      hasPermission: true,
      rightVisiable: false,
      pageInfoVisiable: false,
      ruleStartX: 100,
      ruleStartY: 100,
      zoomList: [
        {
          label: '自适应',
          value: 'auto'
        },
        {
          label: '100%',
          value: 100
        },
        {
          label: '80%',
          value: 80
        },
        {
          label: '50%',
          value: 50
        },
        {
          label: '20%',
          value: 20
        }
      ]
    }
  },
  watch: {
    chartList(val) {
      // if(val.findIndex(item=>item.code==this.activeCode)==-1){
      //   this.updateRightVisiable(false)
      // }
      // if(val.length==0){
      //   this.updateRightVisiable(false)
      // }
    },
    mapShow(value) {
      const mapElement = document.getElementById('minimap')
      // const selectElement = document.getElementById('selectWin')
      if (!value) {
        mapElement.style.bottom = parseFloat(window.getComputedStyle(mapElement).bottom) + 150 + 'px'
      } else {
        this.$refs.Rules.handleScroll()
        mapElement.style.bottom = parseFloat(window.getComputedStyle(mapElement).bottom) - 150 + 'px'
      }
    },
    fitZoom(zoom) {
      this.zoomList[0] = {
        label: `自适应(${zoom}%)`,
        value: zoom
      }
    }
  },
  computed: {
    ...mapState({
      pageInfo: (state) => state.bigScreen.pageInfo,
      chartList: (state) => state.bigScreen.pageInfo.chartList,
      pageConfig: (state) => state.bigScreen.pageInfo.pageConfig,
      pageLoading: (state) => state.bigScreen.pageLoading,
      hoverCode: (state) => state.bigScreen.hoverCode,
      presetLine: (state) => state.bigScreen.presetLine,
      updateKey: (state) => state.bigScreen.updateKey,
      hasGrid: (state) => state.bigScreen.hasGrid,
      zoom: (state) => state.bigScreen.zoom,
      fitZoom: (state) => state.bigScreen.fitZoom,
      iframeDialog: (state) => state.bigScreen.iframeDialog,
      activeCode: state => state.bigScreen.activeCode
    }),
    pageCode() {
      return this.code || this.$route.query.code
    },
    offset() {
      return {
        x: 220 + 50 - this.ruleStartX,
        y: 55 + 50 - this.ruleStartY
      }
    }
  },
  created() {
    this.changePageLoading(true)
    this.permission()
    /**
       * 以下是为了解决在火狐浏览器上推拽时弹出tab页到搜索问题
       * @param event
       */
    if (isFirefox()) {
      document.body.ondrop = function (event) {
        event.preventDefault()
        event.stopPropagation()
      }
    }
  },
  mounted() {
    EventBus.$on('closeRightPanel', () => {
      this.updateRightVisiable(false)
    })
  },
  beforeDestroy() {
    this.clearTimeline()
    EventBus.$off('closeRightPanel')
  },
  methods: {
    ...mapActions('bigScreen', ['initLayout']),
    ...mapMutations('bigScreen', [
      'changeLayout',
      'changePageLoading',
      'resetPresetLine',
      'changeActiveCode',
      'changeActiveCodes',
      'changePageConfig',
      'changeChartConfig',
      'changeChartKey',
      'changeZoom',
      'clearTimeline',
      'saveTimeLine',
      'changeIframeDialog',
      'changePageInfo',
      'changeActiveItemConfig',
      'emptyDataset',
      'emptyComputedDatas'
    ]),
    // 控制小地图显示与隐藏
    showMinimap() {
      this.mapShow = !this.mapShow
    },
    // 判断页面权限
    permission() {
      this.$dataRoomAxios.get(`/bigScreen/permission/check/${this.pageCode}`).then(res => {
        this.hasPermission = res
        if (res) {
          this.init()
        }
      })
    },
    // 添加资源弹窗初始化
    initDialog() {
      this.$refs.SourceDialog.init()
    },
    openComponent() {
      this.$refs.componentDialog.init()
    },
    // 从组件库添加组件模板到当前画布
    setComponent(component) {
      // 根据component获取页面详情
      getScreenInfo(component.code).then(res => {
        res.chartList.forEach((item) => {
          if (!item.border) {
            item.border = { type: '', titleHeight: 60, fontSize: 16, isTitle: true, padding: [0, 0, 0, 0] }
          }
          if (!item.border.padding) {
            item.border.padding = [0, 0, 0, 0]
          }
          if (item.type == 'customComponent') {
            plotSettings[Symbol.iterator] = function* () {
              const keys = Object.keys(plotSettings)
              for (const k of keys) {
                yield [k, plotSettings[k]]
              }
            }
            for (const [key, value] of plotSettings) {
              if (item.name == value.name) {
                const settings = JSON.parse(JSON.stringify(value.setting))
                item.setting = settings.map((x) => {
                  const index = item.setting.findIndex(y => y.field == x.field)
                  x.field = item.setting[index].field
                  x.value = item.setting[index].value
                  return x
                })
              }
            }
          }
        })
        // 给组件库导入的组件加入统一的前缀
        const randomStr = randomString(8)
        const pageInfo = handleResData(res)
        const chartList = pageInfo.chartList.reverse()
        chartList.forEach((chart) => {
          // 如果组件存在数据联动，则将数据联动的code也加上相同的前缀
          if (chart.linkage && chart.linkage.components && chart.linkage.components.length) {
            chart.linkage.components.forEach((com) => { com.componentKey = randomStr + com.componentKey })
          }
          const newChart = {
            ...chart,
            offsetX: 0,
            group: randomStr,
            code: randomStr + chart.code
          }
          // 如果是从组件库中添加的自定义组件，则不需要初始化theme
          const isComponent = true
          this.$refs.Render.addChart(newChart, { x: chart.x, y: chart.y }, isComponent)
          this.updateRightVisiable(false)
        })
      })
    },
    // 添加远程组件
    setRemoteComponent(component) {
      const newChart = {
        ...component,
        offsetX: 0,
        offsetY: 0,
        code: randomString(8)
      }
      this.$refs.Render.addChart(newChart, { x: 0, y: 0 })
    },
    setImg(val) {
      this.$refs.Render.addSourceChart(
        JSON.stringify({
          title: val.originalName,
          name: val.originalName,
          icon: null,
          className:
            'com.gccloud.dataroom.core.module.chart.components.ScreenPictureChart',
          w: 200,
          h: 200,
          x: 0,
          y: 0,
          type: 'picture',
          option: {
            ...cloneDeep(settingConfig)
          },
          setting: {}, // 右侧面板自定义配置
          dataHandler: {}, // 数据自定义处理js脚本
          ...cloneDeep(dataConfig),
          customize: {
            url: val.url,
            radius: 0,
            opacity: 100
          }
        }),
        { x: 250, y: 100 }
      )
    },
    init() {
      this.changePageLoading(true)
      this.initLayout(this.pageCode)
        .then(() => {
          this.changePageLoading(false)
        })
        .finally(() => {
          setTimeout(() => {
            this.resetPresetLine()
          }, 500)
        })
    },
    // 点击当前组件时打开右侧面板
    openRightPanel(card) {
      this.rightVisiable = true
      this.pageInfoVisiable = false
      this.$refs.Rules.initRuleHeight()
    },
    openDataViewDialog(config) {
      this.$refs.dataViewDialog.init(config)
    },
    /**
       * @description: 清空页面
       */
    empty() {
      this.$confirm('确定清空页面吗？', '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning',
        customClass: 'bs-el-message-box'
      })
        .then(() => {
          this.changeLayout([])
          // 清空缓存的数据库的内容
          this.emptyDataset()
          this.emptyComputedDatas()
          this.resetPresetLine()
          this.saveTimeLine('清空画布')
        })
        .catch(() => { })
    },
    // 切换主题时针对远程组件触发样式修改的方法
    styleHandler(config) {
      this.$nextTick(() => {
        this.$refs.Render?.$refs['RenderCard' + config.code][0]?.$refs[
          config.code
        ]?.changeStyle(cloneDeep(config), true)
      })
    },
    // 自定义属性更新
    updateSetting(config) {
      if (config.type === 'map' || config.type === 'screenScrollBoard' || config.type === 'remoteComponent' || config.type === 'video' || config.type === 'flyMap') {
        config.key = new Date().getTime()
      }
      this.changeChartConfig(cloneDeep(config))
      // 如果是tab内的组件
      if (config.parentCode) {
        const dom = this.$refs.Render?.$refs['RenderCard' + config.parentCode][0]?.$refs[config.parentCode]?.$refs['RenderCard' + config.code]?.$refs[config.code]
        if (dom) {
          dom?.changeStyle(cloneDeep(config))
        }
      } else {
        if (this.$refs.Render?.$refs['RenderCard' + config.code]) {
          this.$refs.Render?.$refs['RenderCard' + config.code][0]?.$refs[
            config.code
          ]?.changeStyle(cloneDeep(config))
        }
      }
    },
    // 动态属性更新
    updateDataSetting(config) {
      config.key = new Date().getTime()
      this.changeChartConfig(config)
    },
    onSelectArea(area) {
      const { startX, startY, endX, endY } = area
      // 计算所有在此区域中的组件，如果在此区域中，将其code添加到activeCodes数组中
      const activeCodes = this.chartList
        ?.filter((chart) => {
          const { x, y, w, h } = chart
          return startX - 50 <= x && x + w <= endX && startY - 50 <= y && y + h <= endY
        })
        ?.map((chart) => chart.code)
      this.changeActiveCodes(activeCodes)
    },
    changeStart({ x, y }) {
      this.ruleStartX = x
      this.ruleStartY = y
    },
    // 保存并预览
    saveAndPreview() {
      this.$refs.PageTopSetting.execRun()
    },
    // 保存
    save() {
      this.$refs.PageTopSetting.save('saveLoading')
    },
    changeScreenZoom(zoom) {
      // 自适应
      if (zoom === 'auto') {
        this.$refs.Rules.initZoom()
      } else {
        this.changeZoom(zoom)
      }
    },
    updateRightVisiable(visiable) {
      this.rightVisiable = visiable
      this.$refs.Rules.initRuleHeight()
    },
    toggleLeftSidebar() {
      this.$refs.Rules.initRuleHeight()
    },
    showPageInfo() {
      this.pageInfoVisiable = true
      this.rightVisiable = true
      this.changeActiveCode('')
    },
    // 页面信息更改
    updatePage() {
      this.$refs.Rules.initZoom()
    }
  }
}
</script>
<style lang="scss" scoped>
.bs-page-design-wrap {
  overflow: hidden;

  .drag-wrap {
    display: flex;
    background-color: #1d1e20;
    height: calc(100vh - 40px);
    // overflow: hidden;

    .grid-wrap-box {
      flex: 1;
      // overflow: hidden;
      position: relative;
      margin: 8px 0 0 8px;

      .footer-tools-bar {
        position: absolute;
        bottom: 0;
        width: 100%;
        height: 30px;
        display: flex;
        justify-content: flex-end;
        align-items: center;
        z-index: 1000;
        background-color: var(--bs-background-2);

        .bs-select-wrap {
          margin-right: 16px;
        }

        .select-zoom-text {
          color: var(--bs-el-title);
          margin-right: 16px;
        }

        ::v-deep .el-select {
          width: 150px !important;
        }
      }
    }

    ::v-deep .el-loading-mask {
      background-color: transparent !important;
    }
  }
}

.minimap {
  position: absolute;
  bottom: 20px;
  right: 20px;
  z-index: 1000;
}

.minimap .mapHeader {
  background-color: #303640;
  box-sizing: border-box;
  padding: 0 10px;
  display: flex;
  justify-content: space-between;
  align-items: center;
  height: 30px;
  width: 150px;
  font-size: 12px;
  color: var(--bs-el-title);
  cursor: pointer;

  span {
    user-select: none;
  }
}

.minimap .selectWin {
  background-color: #232832;
  height: 150px;
  width: 150px;
  position: relative;
}

.minimap .selectionWin {
  position: absolute;
  left: 0px;
  top: 0px;
  width: 30px;
  height: 30px;
  background-color: white;
  opacity: 0.5;
  cursor: move;
}
</style>
